<template>
  <div class="datasource-state">

    <FormItemPanel :style="{paddingTop: '10px', paddingBottom: '0px'}">
      <DsResultObjMappingSetting v-if="showMappingSetting && ds_resultObjTemplate && ds_resultObjTemplate.length > 0"></DsResultObjMappingSetting>

      <Button class="m-b-10px" long type="primary" @click="openDatasourceSettingFormDrawer">数据源配置</Button>

      <Checkbox class="m-b-10px" v-model="ds_controlledMode">
        受控模式
        <Tooltip content="开启后，当页面处于预览或发布状态下，组件自身初始化时将不请求数据也不执行任何初始化运行脚本，由其他地方的JS脚本或内置交互流启动器来控制发起首次请求" :max-width="200" placement="top">
          <Icon type="ios-help-circle" size="14"/>
        </Tooltip>
      </Checkbox>

      <Checkbox v-if="ds_useTimer && ds_type != 'websocket' && ds_type != 'shareDatasource'" class="m-b-10px" v-model="ds_autoRefresh">
        自动更新请求，频率 <InputNumber size="small" :max="10000" :min="1" v-model="ds_autoRefreshDuration" style="width: 60px;"></InputNumber> 秒一次
      </Checkbox>

      <Timeline pending>
        <TimelineItem>
          <p>数据源类型：<Tag color="blue">{{ds_type | dsTypeFilter}}</Tag></p>
        </TimelineItem>

        <TimelineItem v-if="ds_type == 'api'">
          <p>接口地址</p>
          <Tag color="green" v-show="ds_apiMethod">请求方式：{{ds_apiMethod}}</Tag><Tag color="cyan" v-if="ds_useHttpServerProxy">服务器代理请求</Tag>
          <Alert class="m-t-5px m-b-5px" :type="ds_apiPath ? 'info': 'warning'" :style="{padding: '10px'}">
            <p style="word-break: break-all">{{ds_apiPath ? ds_apiPath : '未配置接口地址，默认使用上一次结果集数据'}}</p>
          </Alert>
          <Tag color="green" v-for="item in ds_linkageUrlParams" :key="item.id">{{item.field}}</Tag>
        </TimelineItem>

        <TimelineItem v-if="ds_type == 'websocket'">
          <p>WS地址</p>
          <Alert class="m-t-5px m-b-5px" :type="ds_wsPath ? 'info': 'warning'" :style="{padding: '10px'}">
            <p style="word-break: break-all">{{ds_wsPath ? ds_wsPath : '未配置WS地址'}}</p>
          </Alert>
        </TimelineItem>

        <TimelineItem v-if="ds_type == 'database'">
          <p>SQL语句</p>
          <Alert class="m-t-5px m-b-5px" type="info" :style="{padding: '10px'}">
            <p>{{ds_sql}}</p>
          </Alert>
        </TimelineItem>

        <TimelineItem v-if="ds_type == 'shareDatasource'">
          <p>绑定的共享数据源</p>
          <Alert class="m-t-5px m-b-5px" :type="ds_shareDatasourceKey ? 'info': 'warning'" :style="{padding: '10px'}">
            {{ds_shareDatasourceKey ? ds_shareDatasourceKey : '未绑定共享数据源'}}
          </Alert>
        </TimelineItem>

        <TimelineItem v-if="ds_type == 'csv'">
          <p>CSV数据源名称</p>
          <Alert class="m-t-5px m-b-5px" :type="ds_csvDatasourceName ? 'info': 'warning'" :style="{padding: '10px'}">
            <p>{{ds_csvDatasourceName ? ds_csvDatasourceName : '未选择CSV数据源，默认使用上一次结果集数据'}}</p>
          </Alert>
        </TimelineItem>

<!--        <TimelineItem :color="errorAlertVisible?'red':'green'">
          <p>原始响应结果集（静态数据源可直接编辑）</p>
          <Alert v-if="errorAlertVisible" class="m-t-5px m-b-5px" type="error">
            <p>{{errorMsg}}</p>
          </Alert>
          <div class="m-b-5px"></div>
          <CodeEditor v-model="resultObjData" mode="json" :height="200" :readOnly="ds_type != 'static'" @on-submit-change="updateResultObj"></CodeEditor>
        </TimelineItem>-->

        <TimelineItem v-if="ds_filterCode">
          <div>使用了结果集过滤器</div>
          <div class="m-b-5px"></div>
          <Poptip trigger="hover" placement="left" width="300">
            <Button size="small">查看过滤器代码</Button>
            <div slot="content">
              <p>结果集过滤器（只读）</p>
              <CodeEditor v-model="ds_filterCode" :readOnly="true"></CodeEditor>
              <div class="m-b-5px"></div>
            </div>
          </Poptip>
        </TimelineItem>

        <TimelineItem :color="errorAlertVisible?'red':'green'">
          <p>数据结果集（只读）</p>
          <Alert v-if="errorAlertVisible" class="m-t-5px m-b-5px" type="error">
            <p>{{errorMsg}}</p>
          </Alert>
          <div class="m-b-5px"></div>
          <CodeEditor v-model="resultObjDataFiltered" mode="json" :height="280" :readOnly="true"></CodeEditor>
          <Tag v-if="ds_invokeResultClipping" class="m-t-5px" color="warning">结果集已被裁剪，裁剪数量：{{ds_ResultClippingLimit}}</Tag>
        </TimelineItem>

        <TimelineItem v-if="['api','database','csv'].indexOf(ds_type) > -1">
          <p>
            动态加载成功回调脚本
            <Tooltip content="组件采用API、数据库、CSV作为数据源时，当数据调用成功回调时执行的脚本，此脚本只在预览或发布状态下才会运行，作用域与初始化运行脚本中相同，可通过response变量获取动态调用返回的数据" placement="top" max-width="200">
              <Icon type="md-information-circle" size="15"/>
            </Tooltip>
          </p>
          <div class="m-b-5px"></div>
          <CodeEditor v-model="dynamicDatasourceSuccessCallbackCodeData" :height="120" @on-submit-change="updateDynamicDatasourceSuccessCallbackCode"></CodeEditor>
        </TimelineItem>
      </Timeline>

    </FormItemPanel>

    <DatasourceSettingForm :show="datasourceSettingFormDrawerVisible"
                           :targetComp="targetComp"
                           :dsTypesSelectData="dsTypesSelectData"
                           @cancel="datasourceSettingFormDrawerVisible = false"></DatasourceSettingForm>

  </div>
</template>

<script>
  import PnDesigner from "@/utils/PnDesigner";

  import { createHelpers } from 'vuex-map-fields';

  const { mapFields } = createHelpers({
    getterType: 'designer/getLayoutItem',
    mutationType: 'designer/updateLayoutItem',
  });

  export default {
    name: 'DatasourceState',
    props: {
      targetComp: {
        type: String,
        required: true,
        default: '',
      },
      dsTypesSelectData: {
        type: Array,
        default () {
          return []
        }
      },
      showMappingSetting: {
        type: Boolean,
        default: true
      }
    },
    data() {
      return {
        datasourceSettingFormDrawerVisible: false,
        resultObjData: '',
        resultObjDataFiltered: '',

        errorAlertVisible: false,
        errorMsg: '',
        dynamicDatasourceSuccessCallbackCodeData: ''
      }
    },
    mounted() {
      this.resultObjData = JSON.stringify(this.ds_resultObj, null, 2)
      this.dynamicDatasourceSuccessCallbackCodeData = this.ds_dynamicDatasourceSuccessCallbackCode

      this.invokeApiPath();
      this.invokeSql();
      this.checkShareDatasourceKeyExist();
      this.runDsResultObjFilter();
    },
    methods: {
      openDatasourceSettingFormDrawer () {
        this.$PnUtil.showMaskLayer(true);
        setTimeout(()=>{
          this.datasourceSettingFormDrawerVisible = !this.datasourceSettingFormDrawerVisible
        }, 100)
      },

      invokeApiPath () {
        if(this.ds_type == 'api' && this.ds_apiPath) {
          if (this.ds_useHttpServerProxy) {
            this.$PnApi.HttpProxyApi.httpQuery(
                this.ds_apiMethod,
                this.$PnUtil.buildApiPath(this.ds_apiPath, this.ds_linkageUrlParams),
                this.ds_apiHeaders,
                this.ds_apiPostData).then(result => {
              this.errorAlertVisible = false
            }).catch(error => {
              this.errorAlertVisible = true;
              this.errorMsg = JSON.stringify(error, null, 2)
            })
          }else {
            this.$PnApi.httpQuery(
                this.ds_apiMethod,
                this.$PnUtil.buildApiPath(this.ds_apiPath, this.ds_linkageUrlParams),
                this.ds_apiHeaders,
                this.ds_apiPostData).then(result => {
              this.errorAlertVisible = false
            }).catch(error => {
              this.errorAlertVisible = true;
              this.errorMsg = JSON.stringify(error, null, 2)
            })
          }
        }
      },

      invokeSql () {
        if(this.ds_type == 'database' && this.ds_database) {
          this.$PnApi.DatabaseApi.invokeSql(this.ds_database, this.ds_sql).then(result => {
            if (result.data.success) {
              this.errorAlertVisible = false
            }else {
              this.errorAlertVisible = true;
              this.errorMsg = result.data.message
            }
          })
        }
      },

      checkShareDatasourceKeyExist () {
        if(this.ds_type == 'shareDatasource' && this.ds_shareDatasourceKey) {
          let flag = false;
          let layoutItems = this.$store.getters['designer/getLayoutItems'];
          for (let i=0; i<layoutItems.length; i++) {
            if (layoutItems[i].component.id == this.ds_shareDatasourceKey) {
              flag = true
            }
          }
          if (!flag)
            this.$Message.warning({
              content: '关联的共享数据源不存在，可能已被删除，可以在数据源配置中，点击【解除绑定】来取消绑定',
              duration: 8
            })
        }
      },

      updateResultObj () {
        this.$store.commit('designer/updateLayoutItem', {
          path: 'component.compConfigData.ds_resultObj',
          value: JSON.parse(this.resultObjData)
        });
      },

      updateDynamicDatasourceSuccessCallbackCode () {
        this.$store.commit('designer/updateLayoutItem', {
          path: 'component.compConfigData.ds_dynamicDatasourceSuccessCallbackCode',
          value: this.dynamicDatasourceSuccessCallbackCodeData
        });
      },

      runDsResultObjFilter () {
        let promise = new Promise((resolve, reject) => {
          this.$Loading.start()
          try {
            this.resultObjDataFiltered = JSON.stringify(PnDesigner.dsResultObjMappingFilter(this.compConfigData, PnDesigner.dsResultObjCustomCodeFilter(this.compConfigData, this.ds_resultObj)), null, 2)
            resolve()
          }catch (e) {
            reject(e.message)
          }
        })
        promise.then(result => {
          this.$Loading.finish()
        }, error => {
          this.$Loading.error()
        })
      }
    },
    computed: {
      ...mapFields({

        compConfigData: 'component.compConfigData',

        ds_type: 'component.compConfigData.ds_type',
        ds_apiPath: 'component.compConfigData.ds_apiPath',
        ds_apiMethod: 'component.compConfigData.ds_apiMethod',
        ds_apiHeaders: 'component.compConfigData.ds_apiHeaders',
        ds_apiPostData: 'component.compConfigData.ds_apiPostData',
        ds_wsPath: 'component.compConfigData.ds_wsPath',
        ds_database: 'component.compConfigData.ds_database',
        ds_sql: 'component.compConfigData.ds_sql',
        ds_csvDatasourceName: 'component.compConfigData.ds_csvDatasourceName',
        ds_shareDatasourceKey: 'component.compConfigData.ds_shareDatasourceKey',
        ds_resultObjTemplate: 'component.compConfigData.ds_resultObjTemplate',
        ds_resultObj: 'component.compConfigData.ds_resultObj',

        ds_filterCode: 'component.compConfigData.ds_filterCode',

        ds_linkageUrlParams: 'component.compConfigData.ds_linkageUrlParams',

        ds_useTimer: 'component.compConfigData.ds_useTimer',
        ds_autoRefresh: 'component.compConfigData.ds_autoRefresh',
        ds_autoRefreshDuration: 'component.compConfigData.ds_autoRefreshDuration',

        ds_useHttpServerProxy: 'component.compConfigData.ds_useHttpServerProxy',

        ds_dynamicDatasourceSuccessCallbackCode: 'component.compConfigData.ds_dynamicDatasourceSuccessCallbackCode',

        ds_controlledMode: 'component.compConfigData.ds_controlledMode',

        ds_invokeResultClipping: 'component.compConfigData.ds_invokeResultClipping',
        ds_ResultClippingLimit: 'component.compConfigData.ds_ResultClippingLimit',

      }),
    },
    watch: {
      'ds_apiPath': {
        handler: function () {
          this.invokeApiPath()
        }
      },
      'ds_sql': {
        handler: function () {
          this.invokeSql()
        }
      },
      'ds_resultObjTemplate': {
        handler: function (val, oldVal) {
          if(JSON.stringify(val) != JSON.stringify(oldVal)) {
            this.runDsResultObjFilter();
          }
        }
      },
      'ds_filterCode': {
        handler: function () {
          this.runDsResultObjFilter();
        }
      },
      'ds_resultObj': {
        handler: function () {
          this.resultObjData = JSON.stringify(this.ds_resultObj, null, 2);
          this.runDsResultObjFilter();
        }
      },
    },
    filters: {
      dsTypeFilter (value) {
        switch (value) {
          case 'static':
            return '静态数据'
          case 'api':
            return 'API'
          case 'websocket':
            return 'WebSocket'
          case 'database':
            return '数据库'
          case 'shareDatasource':
            return '共享数据源'
          case 'csv':
            return 'CSV文件'
        }
      }
    }
  }
</script>

<style scoped>

  .datasource-state {
    position: relative;
  }

  >>> .ivu-timeline-item-tail {
    border-left: 1px solid #bdbdbd !important;
  }
  >>> .ivu-timeline-item {
    padding: 0 0 0 0 !important;
  }
  >>> .ivu-timeline-item-content {
    min-height: inherit !important;
  }
  >>> .ivu-input {
    background-color: #272822;
    color: #fff;
    border-radius: 0px;
    border: 1px solid #424242;
  }
</style>
